/*
 * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package org.eclipse.imagen;

/**
 * An interface encapsulating the set of operations involved in identifying and reading properties.
 *
 * <p>The interface includes the <code>getProperty()</code> and <code>getPropertyNames()</code> methods familiar from
 * the <code>RenderedImage</code> and <code>RenderableImage</code> interfaces. Classes which implement this interface
 * should do so in a manner which treats the property names as case-retentive. That is to say that as concerns
 * operations effected using the property name as a key, the operation should ignore the case of the property name while
 * on the other hand the property name retrieval methods should return the names with their case preserved.
 *
 * <p><code>PropertySource</code> is implemented by the <code>ImageJAI</code> interface and, among other classes, by
 * <code>PlanarImage</code>, <code>RenderableOp</code> and <code>CollectionImage</code>. Since all <code>RenderedImage
 * </code>s used with JAI are "wrapped" by a <code>RenderedImageAdapter</code>, all JAI <code>RenderedImage</code>s may
 * be assumed to implement <code>PropertySource</code>.
 *
 * <p>If a <code>PropertySource</code> is also a <code>PropertyChangeEmitter</code> then it should fire <code>
 * PropertySourceChangeEvent</code>s to all registered listeners whenever this is reasonable to do so in the context of
 * the <code>PropertySource</code> in question.
 *
 * <p>Property name space collisions may be prevented by adhering to an hierarchical naming convention. This could for
 * example be based on the name of the package in question, e.g., <i>org.eclipse.imagen.media.MyProperty</i>. The names
 * of properties generated by JAI itself will not adhere to the aforementioned naming convention, but this should not
 * pose a problem if users adopt this convention for their own property names.
 *
 * <p>Another approach to handling multiple property name spaces would be to define a separate PropertySource for each
 * name space of properties. These PropertySources could themselves be attached to images as properties. Inheritance of
 * these properties would occur by the default mechanism. Modification of these properties within an operation chain
 * could be managed by PropertyGenerators which are capable of recognizing these properties. Note that a potential
 * problem with this approach exists when a <code>PropertySourceChangeEvent</code> is fired: it might be necessary to
 * clone the entire tree of properties in order to obtain the old value of event object.
 *
 * @see ImageJAI
 * @see PlanarImage
 * @see PropertyChangeEmitter
 * @see WritablePropertySource
 * @see java.awt.image.RenderedImage
 * @see java.awt.image.renderable.RenderableImage
 */
public interface PropertySource {

    /**
     * Returns an array of <code>String</code>s recognized as names by this property source. If no properties are
     * available, <code>null</code> will be returned.
     *
     * @return an array of <code>String</code>s giving the valid property names or <code>null</code>.
     */
    String[] getPropertyNames();

    /**
     * Returns an array of <code>String</code>s recognized as names by this property source that begin with the supplied
     * prefix. If no property names match, <code>null</code> will be returned. The comparison is done in a
     * case-independent manner.
     *
     * @return an array of <code>String</code>s giving the valid property names.
     * @exception IllegalArgumentException if <code>prefix</code> is <code>null</code>.
     */
    String[] getPropertyNames(String prefix);

    /**
     * Returns the class expected to be returned by a request for the property with the specified name. If this
     * information is unavailable, <code>null</code> will be returned indicating that <code>
     * getProperty(propertyName).getClass()</code> should be executed instead. A <code>null</code> value might be
     * returned for example to prevent generating the value of a deferred property solely to obtain its class. <code>
     * null</code> will also be returned if the requested property is not emitted by this property source.
     *
     * @param propertyName the name of the property, as a <code>String</code>.
     * @return The <code>Class</code> expected to be return by a request for the value of this property or <code>null
     *     </code>.
     * @exception IllegalArgumentException if <code>propertyName</code> is <code>null</code>.
     * @since JAI 1.1
     */
    Class getPropertyClass(String propertyName);

    /**
     * Returns the value of a property. If the property name is not recognized, <code>java.awt.Image.UndefinedProperty
     * </code> will be returned.
     *
     * @param propertyName the name of the property, as a <code>String</code>.
     * @return the value of the property, as an <code>Object</code>, or the value <code>java.awt.Image.UndefinedProperty
     *     </code>.
     * @exception IllegalArgumentException if <code>propertyName</code> is <code>null</code>.
     */
    Object getProperty(String propertyName);
}
